Java 是筆者進入 IT 業界的啟蒙老師,歷經了十個年頭,翻過了多少語言的山頭(Python, Golang, C++, PHP...),最近又回鍋寫 Java ,因為她的丰姿,我這個傻瘋子願意在為她奉獻下一個十年,不為別的,只因為她可靠而高效、容易親近但有深度,值得信賴偶爾帶點俏皮,同時她也無所不能,她的好只有老公(程師)懂得!
從 Oracle 大大接手 Java 後,從 8 ~ 17 只花了 (2014 3月 ~ 2022 3月) 8 年,這相當於 Java 從 6 到 8 的時間 (2006 12 月 ~ 2014 3月) ,究竟是 Oracle 對於大版本號碼的解讀不同,還是 Oralce 真的讓他飛了起來,讓我們用 30 天來一探究竟。
允許用更簡潔的 var 來宣告型別,會根據等號右邊的型別做型別推斷
//Java 8
URL url = new URL(”https://www.google.com”);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(”GET”);
//Java 10
var url = new URL(”https://www.google.com”);
var connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(”GET”);
可惜的是,不能用在 Lambda 表達式,之後會介紹 Lambda 表達式其實是一種(函式)類別物件,用函式表達的一種類別物件,可以被指派給物件參考,意即 Lambda 表達式不能指派給 var 物件,不幸中的小確幸是:可以用在 lambda 表達式中的 參數宣告-.-
// compile error!
var fun = MyObject::mySpecialFunction;
// .....mmmmm 其實可以直接不寫 var = =
boolean isThereAneedle = stringsList.stream()
.anyMatch((@NonNull var s) -> s.equals(“needle”));
大家肯定有用過 lombok 吧,lombok 的流行程度同時也是 Java 迷無聲抗議的程度,Records大概就是官方給的回應吧,這個回應超簡短的唷,直接看例子:
// Java 8
@Data
@AllArgConstructor
class Pojo {
private String pojoName;
private String pojoAge;
public Pojo(String pojoName, String pojoAge){
this.pojoName = pojoName;
this.pojoAge = pojoAge;
}
... getter & setter
}
// Java 16
record Pojo(String pojoName, String pojoAge){}
定義 record 類別時,不能使用 hashCode、equals、toString、wait、notify 等作為欄位名稱,record 也不能被繼承。
從 Java 8 到 17 ,增強的 switch 可以有返回值了,如果 case 語句內的程式區塊只有一行,直接回傳,但如果有多行程式,可以使用關鍵字 'yield'
DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
boolean freeDay = false;
// Java 8
switch(dayOfWeek){
case MONDAY:
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
freeDay = false;
case SATURDAY:
case SUNDAY:
freeDay = true;
default:
break;
}
// Java 14
boolean freeDay = switch (dayOfWeek) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> false;
case SATURDAY, SUNDAY -> true;
};
// Using yield
boolean freeDay = switch (dayOfWeek) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {
System.out.println("Work work work");
yield false;
}
case SATURDAY, SUNDAY -> {
System.out.println("Yey, a free day!");
yield true;
}
};
這真的是千呼萬喚始出來的,光這點加上效能上的改進,就值得升級 17 了
// Java 8
String longSQL = "SELECT * FROM user u " +
"LEFT JOIN user_info ui ON u.id=user_info.user_id"
// Java 15
String longSQL = """
SELECT * FROM user u
LEFT JOIN user_info ui ON u.id=user_info.user_id
"""
強制型別轉換一直都是工程師眼裡的一顆老鼠屎啊,Java 17 把屎變不見啦
// Java 8
if(obj instanceof Employee){
Employee emp = (Employee)obj;
return emp.getName();
}
// Java 16
if(obj instanceof Employee emp){
return emp.getName();
}
Sealed class宣告類別(class)及介面(interface)可被哪些類別繼承或實作,換句話說未被sealed class允許的類別或介面則不能繼承或實作。目的是避免被任意繼承造成的混亂。public sealed class Parent premits Child1, Child2 {}
繼承 sealed class 只能是 non-sealed 或是 final 類別,原因很簡單,表示不能在宣告可以被誰誰誰繼承。
所以以下語法會有編譯錯誤:public final class Teacher extends Parent {} //compile error
以前的 NullPointerException 只會丟訊息:
Exception in thread "main":
java.lang.NullPointerException
at Ironman.main(ironman_1.java: 12)
Java 17 會跟你說:
Exception in thread "main":
java.lang.NullPointerException: Cannot read field "x"
because "p" is null
at Ironman.main(ironman_1.java: 12)
https://levelup.gitconnected.com/7-reasons-to-migrate-from-java-8-to-java-17-b8cb031b7af8
https://matthung0807.blogspot.com/2022/04/java-sealed-class.html
https://pretius.com/blog/java-17-features/